*/
+#include "garmin.h"
+
#include <cassert> // for assert
#include <climits> // for INT_MAX
#include <cmath> // for atan2, floor, sqrt
#include <QRegularExpression> // for QRegularExpression
#include <QString> // for QString
#include <QTextCodec> // for QTextCodec
-#include <QVector> // for QVector
#include <Qt> // for CaseInsensitive
#include <QtGlobal> // for qPrintable, foreach
#include "grtcirc.h" // for DEG
#include "jeeps/gpsapp.h" // for GPS_Set_Baud_Rate, GPS_Init, GPS_Pre...
#include "jeeps/gpscom.h" // for GPS_Command_Get_Lap, GPS_Command_Get...
-#include "jeeps/gpsdevice.h" // for gpsdevh
#include "jeeps/gpsmem.h" // for GPS_Track_Del, GPS_Way_Del, GPS_Pvt_Del
#include "jeeps/gpsport.h" // for int32
#include "jeeps/gpsprot.h" // for gps_waypt_type, gps_category_type
#define MYNAME "GARMIN"
-static const char* portname;
-static MakeShort* mkshort_handle;
-static GPS_PWay* tx_waylist;
-static GPS_PWay* tx_routelist;
-static GPS_PWay* cur_tx_routelist_entry;
-static GPS_PTrack* tx_tracklist;
-static GPS_PTrack* cur_tx_tracklist_entry;
-static int my_track_count = 0;
-static char* getposn = nullptr;
-static char* poweroff = nullptr;
-static char* eraset = nullptr;
-static char* resettime = nullptr;
-static char* snlen = nullptr;
-static char* snwhiteopt = nullptr;
-static char* deficon = nullptr;
-static char* category = nullptr;
-static char* categorybitsopt = nullptr;
-static char* baudopt = nullptr;
-static char* opt_codec = nullptr;
-static int baud = 0;
-static int categorybits;
-static bool receiver_must_upper = true;
-static QTextCodec* codec{nullptr};
#define MILITANT_VALID_WAYPT_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-/* Technically, even this is a little loose as spaces aren't allowed */
-static const char* valid_waypt_chars = MILITANT_VALID_WAYPT_CHARS " ";
-static QRegularExpression invalid_char_re;
-
-static
-QVector<arglist_t> garmin_args = {
- {
- "snlen", &snlen, "Length of generated shortnames", nullptr,
- ARGTYPE_INT, "1", nullptr, nullptr
- },
- {
- "snwhite", &snwhiteopt, "Allow whitespace synth. shortnames",
- nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
- },
- { "deficon", &deficon, "Default icon name", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr },
- {
- "get_posn", &getposn, "Return current position as a waypoint",
- nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
- },
- {
- "power_off", &poweroff, "Command unit to power itself down",
- nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
- },
- {
- "erase_t", &eraset, "Erase existing courses when writing new ones",
- nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
- },
- {
- "resettime", &resettime, "Sync GPS time to computer time",
- nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
- },
- {
- "category", &category, "Category number to use for written waypoints",
- nullptr, ARGTYPE_INT, "1", "16", nullptr
- },
- {
- "bitscategory", &categorybitsopt, "Bitmap of categories",
- nullptr, ARGTYPE_INT, "1", "65535", nullptr
- },
- {
- "baud", &baudopt, "Speed in bits per second of serial port (baud=9600)",
- nullptr, ARGTYPE_INT, ARG_NOMINMAX, nullptr
- },
- {
- "codec", &opt_codec, "override codec to use for device",
- nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr
- },
-
-};
-
-static const char* d103_symbol_from_icon_number(unsigned int n);
-static int d103_icon_number_from_symbol(const QString& s);
-static void garmin_fs_garmin_after_read(GPS_PWay way, Waypoint* wpt, int protoid);
-static void garmin_fs_garmin_before_write(const Waypoint* wpt, GPS_PWay way, int protoid);
-
-static QByteArray str_from_unicode(const QString& qstr)
+
+QByteArray GarminFormat::str_from_unicode(const QString& qstr)
{
return codec->fromUnicode(qstr);
}
-static QString str_to_unicode(const QByteArray& cstr)
+QString GarminFormat::str_to_unicode(const QByteArray& cstr)
{
return codec->toUnicode(cstr);
}
-static void
-write_char_string(char* dest, const char* source, size_t destsize)
+void
+GarminFormat::write_char_string(char* dest, const char* source, size_t destsize)
{
// we zero fill and always terminate within the dest buffer.
strncpy(dest, source, destsize - 1);
dest[destsize-1] = 0;
}
-static void
-rw_init(const QString& fname)
+void
+GarminFormat::rw_init(const QString& fname)
{
receiver_must_upper = true;
const char* receiver_charset = "US-ASCII";
+ /* Technically, even this is a little loose as spaces aren't allowed */
+ const char* valid_waypt_chars = MILITANT_VALID_WAYPT_CHARS " ";
if (!mkshort_handle) {
mkshort_handle = new MakeShort;
assert(invalid_char_re.isValid());
}
-static void
-rd_init(const QString& fname)
+void
+GarminFormat::rd_init(const QString& fname)
{
rw_init(fname);
}
-static void
-rw_deinit()
+void
+GarminFormat::rw_deinit()
{
if (gps_baud_rate != DEFAULT_BAUD) {
if (0 == GPS_Set_Baud_Rate(portname, DEFAULT_BAUD)) {
portname = nullptr;
}
-static int
-waypt_read_cb(int total_ct, GPS_PWay* /*unused*/)
+int
+GarminFormat::waypt_read_cb(int total_ct, GPS_PWay* /*unused*/)
{
if (global_opts.verbose_status) {
static int i;
return 0;
}
-static void
-waypt_read()
+void
+GarminFormat::waypt_read()
{
int n;
GPS_PWay* way = nullptr;
}
}
-static int lap_read_nop_cb(int /*unused*/, GPS_SWay** /*unused*/)
+int GarminFormat::lap_read_nop_cb(int /*unused*/, GPS_SWay** /*unused*/)
{
return 0;
}
// returns 1 if the waypoint's start_time can be found
// in the laps array, 0 otherwise
-static unsigned int checkWayPointIsAtSplit(Waypoint* wpt, GPS_PLap* laps, int nlaps)
+unsigned int GarminFormat::checkWayPointIsAtSplit(Waypoint* wpt, GPS_PLap* laps, int nlaps)
{
int result = 0;
return result;
}
-static
void
-track_read()
+GarminFormat::track_read()
{
GPS_PTrack* array;
route_head* trk_head = nullptr;
xfree(array);
}
-static
void
-route_read()
+GarminFormat::route_read()
{
GPS_PWay* array;
/* TODO: Fixes warning but is it right?
* code, we convert the PVT (position/velocity/time) data from the receiver
* to the data type we use throughout. Yes, we do lose some data that way.
*/
-static void
-pvt2wpt(GPS_PPvt_Data pvt, Waypoint* wpt)
+void
+GarminFormat::pvt2wpt(GPS_PPvt_Data pvt, Waypoint* wpt)
{
wpt->altitude = pvt->alt;
wpt->latitude = pvt->lat;
}
}
-static gpsdevh* pvt_fd;
-
-static void
-pvt_init(const QString& fname)
+void
+GarminFormat::rd_position_init(const QString& fname)
{
rw_init(fname);
GPS_Command_Pvt_On(qPrintable(fname), &pvt_fd);
}
-static Waypoint*
-pvt_read(posn_status* posn_status)
+Waypoint*
+GarminFormat::rd_position(posn_status* posn_status)
{
auto* wpt = new Waypoint;
GPS_PPvt_Data pvt = GPS_Pvt_New();
return nullptr;
}
-static void
-data_read()
+void
+GarminFormat::read()
{
if (poweroff) {
return;
}
}
-static GPS_PWay
-sane_GPS_Way_New()
+GPS_PWay
+GarminFormat::sane_GPS_Way_New()
{
GPS_PWay way = GPS_Way_New();
if (!way) {
return way;
}
-static int
-waypt_write_cb(GPS_PWay* /*unused*/)
+int
+GarminFormat::waypt_write_cb(GPS_PWay* /*unused*/)
{
int n = waypt_count();
* If we're using smart names, try to put the cache info in the
* description.
*/
-static const char*
-get_gc_info(const Waypoint* wpt)
+const char*
+GarminFormat::get_gc_info(const Waypoint* wpt)
{
if (global_opts.smart_names) {
if (wpt->gc_data->type == Geocache::type_t::gt_virtual) {
return "";
}
-static int
-waypoint_prepare()
+int
+GarminFormat::waypoint_prepare()
{
int i;
int n = waypt_count();
* cleaning
*/
QByteArray ident = mkshort_handle->mkshort(
- global_opts.synthesize_shortnames ?
- str_from_unicode(src) :
- str_from_unicode(wpt->shortname),
- false);
+ global_opts.synthesize_shortnames ?
+ str_from_unicode(src) :
+ str_from_unicode(wpt->shortname),
+ false);
/* Should not be a strcpy as 'ident' isn't really a C string,
* but rather a garmin "fixed length" buffer that's padded
* to the end with spaces. So this is NOT (strlen+1).
return n;
}
-static void
-waypoint_write()
+void
+GarminFormat::waypoint_write()
{
int n = waypoint_prepare();
xfree(tx_waylist);
}
-static void
-route_hdr_pr(const route_head* rte)
+void
+GarminFormat::route_hdr_pr(const route_head* rte)
{
(*cur_tx_routelist_entry)->rte_num = rte->rte_num;
(*cur_tx_routelist_entry)->isrte = 1;
}
}
-static void
-route_waypt_pr(const Waypoint* wpt)
+void
+GarminFormat::route_waypt_pr(const Waypoint* wpt)
{
GPS_PWay rte = *cur_tx_routelist_entry;
cur_tx_routelist_entry++;
}
-static void
-route_write()
+void
+GarminFormat::route_write()
{
int n = 2 * route_waypt_count(); /* Doubled for the islink crap. */
tx_routelist[i] = sane_GPS_Way_New();
}
- route_disp_all(route_hdr_pr, nullptr, route_waypt_pr);
+ auto route_hdr_pr_lambda = [this](const route_head* rte)->void {
+ route_hdr_pr(rte);
+ };
+ auto route_waypt_pr_lambda = [this](const Waypoint* waypointp)->void {
+ route_waypt_pr(waypointp);
+ };
+ route_disp_all(route_hdr_pr_lambda, nullptr, route_waypt_pr_lambda);
GPS_Command_Send_Route(portname, tx_routelist, n);
}
-static void
-track_hdr_pr(const route_head* trk_head)
+void
+GarminFormat::track_hdr_pr(const route_head* trk_head)
{
(*cur_tx_tracklist_entry)->ishdr = true;
if (!trk_head->rte_name.isEmpty()) {
my_track_count++;
}
-static void
-track_waypt_pr(const Waypoint* wpt)
+void
+GarminFormat::track_waypt_pr(const Waypoint* wpt)
{
(*cur_tx_tracklist_entry)->lat = wpt->latitude;
(*cur_tx_tracklist_entry)->lon = wpt->longitude;
cur_tx_tracklist_entry++;
}
-static int
-track_prepare()
+int
+GarminFormat::track_prepare()
{
- int32_t n = track_waypt_count() + track_count();
+ int32_t n = track_waypt_count() + track_count();
tx_tracklist = (GPS_STrack**) xcalloc(n, sizeof(GPS_PTrack));
cur_tx_tracklist_entry = tx_tracklist;
tx_tracklist[i] = GPS_Track_New();
}
my_track_count = 0;
- track_disp_all(track_hdr_pr, nullptr, track_waypt_pr);
+ auto track_hdr_pr_lambda = [this](const route_head* rte)->void {
+ track_hdr_pr(rte);
+ };
+ auto track_waypt_pr_lambda = [this](const Waypoint* waypointp)->void {
+ track_waypt_pr(waypointp);
+ };
+ track_disp_all(track_hdr_pr_lambda, nullptr, track_waypt_pr_lambda);
GPS_Prepare_Track_For_Device(&tx_tracklist, &n);
return n;
}
-static void
-track_write()
+void
+GarminFormat::track_write()
{
int n = track_prepare();
GPS_Command_Send_Track(portname, tx_tracklist, n, (eraset)? 1 : 0);
xfree(tx_tracklist);
}
-static void
-course_write()
+void
+GarminFormat::course_write()
{
int i;
xfree(tx_tracklist);
}
-static void
-data_write()
+void
+GarminFormat::write()
{
if (poweroff) {
return;
}
}
-
-ff_vecs_t garmin_vecs = {
- ff_type_serial,
- FF_CAP_RW_ALL,
- rd_init,
- rw_init,
- rw_deinit,
- rw_deinit,
- data_read,
- data_write,
- nullptr,
- &garmin_args,
- { pvt_init, pvt_read, rw_deinit, nullptr, nullptr, nullptr }
-};
-
-static const char* d103_icons[16] = {
- "dot",
- "house",
- "gas",
- "car",
- "fish",
- "boat",
- "anchor",
- "wreck",
- "exit",
- "skull",
- "flag",
- "camp",
- "circle_x",
- "deer",
- "1st_aid",
- "back-track"
-};
-
-static const char*
-d103_symbol_from_icon_number(unsigned int n)
+const char*
+GarminFormat::d103_symbol_from_icon_number(unsigned int n)
{
if (n <= 15) {
return d103_icons[n];
}
}
-static int
-d103_icon_number_from_symbol(const QString& s)
+int
+GarminFormat::d103_icon_number_from_symbol(const QString& s)
{
if (s.isNull()) {
return 0;
return 0;
}
-static void
-garmin_fs_garmin_after_read(const GPS_PWay way, Waypoint* wpt, const int protoid)
+void
+GarminFormat::garmin_fs_garmin_after_read(const GPS_PWay way, Waypoint* wpt, const int protoid)
{
auto* gmsd = new garmin_fs_t(protoid);
wpt->fs.FsChainAdd(gmsd);
garmin_fs_t::set_addr(gmsd, str_to_unicode(QByteArray(way->addr, qstrnlen(way->addr, sizeof(way->addr)))));
}
-static void
-garmin_fs_garmin_before_write(const Waypoint* wpt, GPS_PWay way, const int protoid)
+void
+GarminFormat::garmin_fs_garmin_before_write(const Waypoint* wpt, GPS_PWay way, const int protoid)
{
const garmin_fs_t* gmsd = garmin_fs_t::find(wpt);
--- /dev/null
+/*
+ Jeeps wrapper for Garmin serial protocol.
+
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Robert Lipe, robertlipe+source@gpsbabel.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ */
+#ifndef GARMIN_H_INCLUDED_
+#define GARMIN_H_INCLUDED_
+
+#include <cstdio> // for size_t
+
+#include <QByteArray> // for QByteArray
+#include <QRegularExpression> // for QRegularExpression
+#include <QString> // for QString
+#include <QTextCodec> // for QTextCodec
+#include <QVector> // for QVector
+
+#include "defs.h"
+#include "format.h" // for Format
+#include "jeeps/gpsdevice.h" // for gpsdevh
+#include "jeeps/gpssend.h" // for GPS_PWay, GPS_SWay, GPS_PTrack, GPS_PPvt_Data, GPS_SLap
+#include "mkshort.h" // for MakeShort
+
+
+class GarminFormat : public Format
+{
+public:
+ QVector<arglist_t>* get_args() override
+ {
+ return &garmin_args;
+ }
+
+ ff_type get_type() const override
+ {
+ return ff_type_serial;
+ }
+
+ QVector<ff_cap> get_cap() const override
+ {
+ return FF_CAP_RW_ALL;
+ }
+
+ void rd_init(const QString& fname) override;
+ void read() override;
+ void rd_deinit() override
+ {
+ rw_deinit();
+ }
+ void wr_init(const QString& fname) override
+ {
+ rw_init(fname);
+ }
+ void write() override;
+ void wr_deinit() override
+ {
+ rw_deinit();
+ }
+ void rd_position_init(const QString& fname) override;
+ Waypoint* rd_position(posn_status* status) override;
+ void rd_position_deinit() override
+ {
+ rw_deinit();
+ }
+
+private:
+ /* Member Functions */
+
+ QByteArray str_from_unicode(const QString& qstr);
+ QString str_to_unicode(const QByteArray& cstr);
+ static void write_char_string(char* dest, const char* source, size_t destsize);
+ void rw_init(const QString& fname);
+ void rw_deinit();
+ static int waypt_read_cb(int total_ct, GPS_SWay** /* unused */);
+ void waypt_read();
+ static int lap_read_nop_cb(int /* unused */, GPS_SWay** /* unused */);
+ static unsigned int checkWayPointIsAtSplit(Waypoint* wpt, GPS_SLap** laps, int nlaps);
+ void track_read();
+ void route_read();
+ static void pvt2wpt(GPS_PPvt_Data pvt, Waypoint* wpt);
+ static GPS_SWay* sane_GPS_Way_New();
+ static int waypt_write_cb(GPS_SWay** /* unused */);
+ static const char* get_gc_info(const Waypoint* wpt);
+ int waypoint_prepare();
+ void waypoint_write();
+ void route_hdr_pr(const route_head* rte);
+ void route_waypt_pr(const Waypoint* wpt);
+ void route_write();
+ void track_hdr_pr(const route_head* trk_head);
+ void track_waypt_pr(const Waypoint* wpt);
+ int track_prepare();
+ void track_write();
+ void course_write();
+ static const char* d103_symbol_from_icon_number(unsigned int n);
+ static int d103_icon_number_from_symbol(const QString& s);
+ void garmin_fs_garmin_after_read(GPS_PWay way, Waypoint* wpt, int protoid);
+ void garmin_fs_garmin_before_write(const Waypoint* wpt, GPS_PWay way, int protoid);
+
+ /* Data Members */
+
+ const char* portname{};
+ MakeShort* mkshort_handle{};
+ GPS_PWay* tx_waylist{};
+ GPS_PWay* tx_routelist{};
+ GPS_PWay* cur_tx_routelist_entry{};
+ GPS_PTrack* tx_tracklist{};
+ GPS_PTrack* cur_tx_tracklist_entry{};
+ int my_track_count = 0;
+ char* getposn = nullptr;
+ char* poweroff = nullptr;
+ char* eraset = nullptr;
+ char* resettime = nullptr;
+ char* snlen = nullptr;
+ char* snwhiteopt = nullptr;
+ char* deficon = nullptr;
+ char* category = nullptr;
+ char* categorybitsopt = nullptr;
+ char* baudopt = nullptr;
+ char* opt_codec = nullptr;
+ int baud = 0;
+ int categorybits{};
+ bool receiver_must_upper = true;
+ QTextCodec* codec{nullptr};
+
+ QRegularExpression invalid_char_re;
+
+ QVector<arglist_t> garmin_args = {
+ {
+ "snlen", &snlen, "Length of generated shortnames", nullptr,
+ ARGTYPE_INT, "1", nullptr, nullptr
+ },
+ {
+ "snwhite", &snwhiteopt, "Allow whitespace synth. shortnames",
+ nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
+ },
+ { "deficon", &deficon, "Default icon name", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr },
+ {
+ "get_posn", &getposn, "Return current position as a waypoint",
+ nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
+ },
+ {
+ "power_off", &poweroff, "Command unit to power itself down",
+ nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
+ },
+ {
+ "erase_t", &eraset, "Erase existing courses when writing new ones",
+ nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
+ },
+ {
+ "resettime", &resettime, "Sync GPS time to computer time",
+ nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
+ },
+ {
+ "category", &category, "Category number to use for written waypoints",
+ nullptr, ARGTYPE_INT, "1", "16", nullptr
+ },
+ {
+ "bitscategory", &categorybitsopt, "Bitmap of categories",
+ nullptr, ARGTYPE_INT, "1", "65535", nullptr
+ },
+ {
+ "baud", &baudopt, "Speed in bits per second of serial port (baud=9600)",
+ nullptr, ARGTYPE_INT, ARG_NOMINMAX, nullptr
+ },
+ {
+ "codec", &opt_codec, "override codec to use for device",
+ nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr
+ },
+
+ };
+
+ gpsdevh* pvt_fd{};
+
+ static constexpr const char* d103_icons[16] = {
+ "dot",
+ "house",
+ "gas",
+ "car",
+ "fish",
+ "boat",
+ "anchor",
+ "wreck",
+ "exit",
+ "skull",
+ "flag",
+ "camp",
+ "circle_x",
+ "deer",
+ "1st_aid",
+ "back-track"
+ };
+};
+#endif // GARMIN_H_INCLUDED_